package DAO.mysql;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

import model.core.code.IEntrance;
import model.core.code.MethodToken;
import model.core.graph.IToken;
import DAO.IDAO;
import DAO.IWordCodeDAO;
import DAO.IWordDAO;

public class MySQLWordCodeDAO implements IWordCodeDAO {
	private MySQLConnectionPool pool;
	private IDAO dao;
	
	public MySQLWordCodeDAO(MySQLConnectionPool pool, IDAO dao) {
		this.pool = pool;
		this.dao = dao;
	}
//	public MySQLWordCodeDAO(MySQLConnectionPool pool2, MySQLDAO dao2) {
//		// TODO Auto-generated constructor stub
//	}
	@Override
	public void addConnection(IEntrance entrance, IToken[] token) {
		if(token == null) return;
		Connection conn = null;
		PreparedStatement stmt = null;
		CallableStatement call = null;
		try {
			conn = pool.getConnection();
			stmt = conn.prepareStatement("INSERT ignore INTO entr2word(entrID, nodeID, tkenIdx) values(?,?,?)");
			call = conn.prepareCall("call addTokenCount(?,?,?)");
			for(int i = 0; i < token.length; ++i) {
				if(token[i] != null) {
					stmt.setInt(1, entrance.getID());
					stmt.setInt(2, token[i].getID());
					stmt.setInt(3, i);
					stmt.execute();
					call.setInt(1, entrance.getID());
					call.setInt(2, token[i].getID());
					call.setInt(3, i);
					call.execute();
				}
			}
		} catch(Throwable e) {
			e.printStackTrace();
		} finally {
			if(stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(call != null) {
				try {
					call.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(conn != null) {
				pool.returnConnection(conn);
			}
		}
	}

	@Override
	public void addConnection(MethodToken mthdToken, IToken[] token) {
		if(token == null) return;
		Connection conn = null;
		PreparedStatement stmt = null;
		CallableStatement call = null;
		try {
			conn = pool.getConnection();
			stmt = conn.prepareStatement("INSERT ignore INTO mthd2word(entrID, nodeID, tkenIdx) values(?,?,?)");
			call = conn.prepareCall("call addTokenCount(?,?,?)");
			for(int i = 0; i < token.length; ++i) {
				if(token[i] != null) {
					stmt.setInt(1, mthdToken.getTokenID());
					stmt.setInt(2, token[i].getID());
					stmt.setInt(3, i);
					stmt.execute();
					call.setInt(1, mthdToken.getTokenID());
					call.setInt(2, token[i].getID());
					call.setInt(3, i);
					call.execute();
				}
			}
		} catch(Throwable e) {
			e.printStackTrace();
		} finally {
			if(stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(call != null) {
				try {
					call.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(conn != null) {
				pool.returnConnection(conn);
			}
		}
	}
	
	@Override
	public List<IEntrance> getRelatedEntrance(IToken token) {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		
		try {
			conn = this.pool.getConnection();
			stmt = conn.prepareStatement("SELECT * FROM entr2word where nodeID=?");
			stmt.setInt(1, token.getID());
			rs = stmt.executeQuery();
			List<IEntrance> entrs = new LinkedList<IEntrance>();
			while(rs.next()) {
				int entrID = rs.getInt(1);
				IEntrance entr = dao.getCodeDAO().getEntrance(entrID);
				entrs.add(entr);
			}
			return entrs;
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if(rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(conn != null) {
				pool.returnConnection(conn);
			}
		}
		return null;
	}
	
	@Override
	public List<MethodToken> getRelatedMethodToken(IToken token) {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		
		try {
			conn = this.pool.getConnection();
			stmt = conn.prepareStatement("SELECT * FROM mthd2word where nodeID=?");
			stmt.setInt(1, token.getID());
			rs = stmt.executeQuery();
			List<MethodToken> entrs = new LinkedList<MethodToken>();
			while(rs.next()) {
				int mthdID = rs.getInt(1);
				MethodToken mTken = dao.getCodeDAO().getMethodToken(mthdID);
				entrs.add(mTken);
			}
			return entrs;
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if(rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(conn != null) {
				pool.returnConnection(conn);
			}
		}
		return null;
	}

}
